<template>
  <div class="comment-item flex-1 flex flex-col overflow-hidden">
    <!-- 评论顶部信息 -->
    <div class="flex justify-between mb-3">
      <span class="teld-color-gray font-semibold">{{ userNameDisplay }}</span>
      <!-- <span :title="comment.CommentTime" class="teld-color-gray">
        {{ comment.CommentTimeRelative }}
      </span> -->
    </div>

    <!-- 评论内容行 -->
    <div class="comment-content mb-2">
      <div
        v-if="comment.ReferenceTitle && !comment.ReferenceTitle.trim()"
        :title="comment.ReferenceTitle"
        class="comment-content--reference teld-color-lightgray truncate mb-1 pl-2"
        style="border-left: 4px solid lightgray"
      >
        {{ comment.ReferenceTitle }}
      </div>
      <div
        v-if="!comment.IsDeleted"
        v-html="decodeURIComponent(comment.Content)"
        class="break-all"
        @click="onClickContent"
      ></div>
      <div v-else class="teld-color-gray">{{
        /*该条评论已删除*/
        qLangComment.commentIsDeleted
      }}</div>
    </div>

    <!-- 附件 -->
    <section
      v-if="
        !comment.IsDeleted && comment.Attachments && comment.Attachments.length
      "
      class="attachments-section w-full"
      :class="[dense ? 'mb-1' : 'mb-2']"
    >
      <div
        v-for="attachment in comment.Attachments"
        :key="attachment.ID"
        class="attachment-file flex items-center"
        :class="[dense ? '' : 'py-1']"
        @click="onClickAttachment(attachment)"
      >
        <!-- 文件类型图标 -->
        <FileTypeIcon :file-name="attachment.FileName" class="w-6 h-6 mr-2" />
        <!-- 文件名 -->
        <div
          class="flex-1 mr-2 truncate text-xs overflow-hidden"
          :title="attachment.FileName"
        >
          {{ attachment.FileName }}
        </div>
      </div>
    </section>

    <!-- 评论底部按钮行 -->
    <div v-if="!comment.IsDeleted" class="flex justify-between">
      <span :title="comment.CommentTime" class="teld-color-gray">{{
        comment.CommentTimeRelative
      }}</span>

      <div
        class="comment-operations flex justify-end"
        :class="[disabled ? 'teld-color-lightgray' : 'teld-color-gray']"
      >
        <!-- 点赞 -->
        <div
          class="comment-like flex rounded-sm leading-5 hover:text-theme-color"
          :class="[disabled ? 'cursor-not-allowed' : 'cursor-pointer']"
          @click="onClickLike"
        >
          <SvgHeartFilled v-show="comment.Liked" class="mr-1" />
          <SvgHeart v-show="!comment.Liked" class="mr-1" />
          <span class="">{{ comment.LikeCount || 0 }}</span>
        </div>
        <!-- 收藏 -->
        <div
          class="comment-star flex ml-2 rounded-sm leading-5 hidden"
          :class="[disabled ? 'cursor-not-allowed' : 'cursor-pointer']"
          @click="onClickFavorite"
        >
          <SvgStarFilled v-show="comment.IsFavorite" class="mr-1" />
          <SvgStar v-show="!comment.IsFavorite" class="mr-1" />
          <span class="">
            {{ comment.FavoriteCount || 0 }}
          </span>
        </div>
        <!-- 回复 -->
        <div
          class="comment-reply ml-2 rounded-sm hover:text-theme-color"
          :class="[
            disabled ? 'cursor-not-allowed' : 'cursor-pointer',
            inputVisible ? 'teld-theme-color' : 'teld-color-gray',
          ]"
          @click="onClickReply"
        >
          {{ /*回复*/ qLangComment.reply }}
        </div>
        <!-- 删除 -->
        <div
          v-if="comment.CanCancel && !disabled"
          class="comment-revoke ml-2 rounded-sm hover:text-theme-color"
          @click="onClickRevoke"
        >
          {{ /*删除*/ qLangComment.delete }}
        </div>
      </div>
    </div>

    <!-- 评论的回复框 -->
    <draft-editor
      ref="draftEditorRef"
      v-model:visible="inputVisible"
      :placeholder="inputPlaceholder"
      class="h-0"
      @comment="onReplyToComment"
    />

    <!-- 本评论的回复列表Top2 -->
    <div
      v-if="!comment.IsDeleted && comment.RepliesTop2.length"
      class="reply-list p-2 teld-bg-color-gray rounded w-full"
      :class="dense ? 'mt-1' : 'mt-2'"
    >
      <ReplyItem
        v-for="(reply, i) in comment.RepliesTop2"
        :key="reply.ID"
        :data-item="comment.RepliesTop2[i]"
        :is-comment-deleted="comment.IsDeleted"
        class="mr-1"
        :class="[i > 0 ? (dense ? 'mt-1' : 'mt-2') : '']"
        @reply="onReplyToReply"
        @delete="onReplyDelete"
      />

      <div
        v-show="comment.ReplyCount > 2"
        class="teld-color-gray text-center"
        :class="[
          disabled ? 'cursor-not-allowed' : 'cursor-pointer',
          dense ? 'mt-1' : 'mt-2',
        ]"
        @click="showAllReplies"
      >
        <!-- 查看全部 {{ comment.ReplyCount }} 条回复 -->
        {{ qLangComment.funcViewAllReplies(comment.ReplyCount) }}
      </div>
    </div>

    <CommentRepliesPopup
      v-model:visible="commentRepliesPopupVisible"
      :data-item="comment"
      @reply="onAddReplyInPopup"
      @delete-reply="onDeleteReplyInPopup"
    ></CommentRepliesPopup>

    <!-- <PersonnelInfoPopup
      v-model:visible="personnelInfoVisible"
      v-model:user-id="mentionedUserId"
    /> -->

    <!-- 大图查看 -->
    <t-image-preview
      ref="imagePreviewRef"
      v-model="currentImgSrc"
      :src-list="previewSrcList"
    ></t-image-preview>
  </div>
</template>

<script>
// Components
import SvgHeart from '../../components/svg-icons/heart.vue';
import SvgHeartFilled from '../../components/svg-icons/heart-filled.vue';
import SvgStar from '../../components/svg-icons/star.vue';
import SvgStarFilled from '../../components/svg-icons/star-filled.vue';
import ReplyItem from '../reply-item/index.vue';
import DraftEditor from '../draft-editor/index.vue';
import CommentRepliesPopup from '../comment-replies-popup/index.vue';
import FileTypeIcon from '../../components/file-type-icon/index.vue';
// import PersonnelInfoPopup from '../personnel-info-popup/index.vue';

// Utils
import { useRelativeTime, saveAs } from '../../hooks';
import dayjs from 'dayjs';
import {
  deleteComment,
  turnOnLike,
  cancelLike,
  saveReply,
} from '../../hooks/api';

export default {
  name: 'CommentItem',
  inject: [
    'loginUserInfo',
    // 'pageUrl',
    'notificationLink',
    'qLangComment',
    'dense',
  ],
  props: {
    dataItem: {
      type: Object,
      default: () => {},
    },
  },
  components: {
    SvgHeart,
    SvgHeartFilled,
    SvgStar,
    SvgStarFilled,
    ReplyItem,
    DraftEditor,
    CommentRepliesPopup,
    FileTypeIcon,
    // PersonnelInfoPopup,
  },
  data() {
    return {
      inputVisible: false,
      comment: {},
      commentRepliesPopupVisible: false,
      previewSrcList: [],
      currentImgSrc: '',
      //
      personnelInfoVisible: false,
      mentionedUserId: null,
    };
  },
  computed: {
    disabled() {
      return this.comment.IsDeleted;
    },
    isAuthor() {
      const loginUser = this.loginUserInfo;
      return loginUser.userId === this.comment.UserID;
    },
    userNameDisplay() {
      return this.isAuthor ? '我' : this.comment.UserName;
    },
    inputPlaceholder() {
      return `回复 ${this.userNameDisplay}`;
    },
  },
  created() {
    const { CommentTime, ReplyCount, Replies } = this.dataItem;
    const timeRelative = useRelativeTime(this.$q.lang.relativeTime)(
      CommentTime,
    );
    const top2Replies =
      ReplyCount > 2 ? Replies.slice(0, 2) || [] : Replies || [];

    this.comment = {
      ...this.dataItem,
      CommentTimeRelative: timeRelative || '',
      RepliesTop2: top2Replies,
      CommentTime: dayjs(CommentTime).format('YYYY/MM/DD HH:mm:ss'),
    };
  },
  mounted() {
    this.initImagePreview();
  },
  methods: {
    initImagePreview() {
      const elImages = this.$el.querySelectorAll('.comment-content img');
      this.previewSrcList = [].map.call(elImages, elImage => {
        return elImage.src;
      });
    },
    async onClickLike() {
      if (this.disabled) return;
      const isLike = (this.comment.Liked = !this.comment.Liked);
      const diff = isLike ? 1 : -1;
      this.comment.LikeCount += diff;
      let succeeded = false;

      const payload = isLike
        ? { CommentID: this.comment.ID, TargetID: 0 }
        : { Id: this.comment.ID };
      const updateLikeState = isLike ? turnOnLike : cancelLike;
      try {
        const res = await updateLikeState(payload);

        if (res.state !== '1') {
          return;
        }

        succeeded = true;
        // this.$TM.Toast(isLike ? '已点赞' : '已取消点赞');
      } catch (error) {
        console.log(error);
      } finally {
        // 接口调用失败后，页面状态回滚
        if (!succeeded) {
          this.comment.Liked = !isLike;
          this.comment.LikeCount -= diff;
        }
      }
    },
    async onClickFavorite() {
      if (this.disabled) return;
      this.comment.IsFavorite = !this.comment.IsFavorite;
      const diff = this.comment.IsFavorite ? 1 : -1;
      this.comment.FavoriteCount += diff;
      // TODO 调接口
    },
    onClickReply() {
      if (this.disabled) return;
      this.inputVisible = true;
    },
    async handleDeleteComment() {
      this.comment.IsDeleted = true;
      const onFail = () => {
        this.comment.IsDeleted = false;
        this.comment.CanCancel = false;
        // this.$TM.Toast('删除失败');
        this.$q.notify(this.qLangComment.deleteFailed);
      };

      try {
        const res = await deleteComment(this.comment.ID);

        if (!res || res.state !== '1') {
          onFail();
          return;
        }
        // this.$TM.Toast('已删除');
        this.$q.notify(this.qLangComment.deleteDone);
        this.$emit('decrease', this.comment.ReplyCount + 1);
      } catch (error) {
        console.log(error);
        onFail();
      }
    },
    /** 点击删除（评论） */
    async onClickRevoke() {
      if (this.disabled) return;

      this.$q
        .dialog({
          title: this.qLangComment.confirmation,
          message: this.qLangComment.deleteConfirmation,
          cancel: true,
          persistent: true,
        })
        .onOk(() => {
          console.log('>>>> OK');
          this.handleDeleteComment();
        })
        .onCancel(() => {
          console.log('>>>> Cancel');
        });
    },
    async onReplyToComment(draftInfo) {
      const loginUser = this.loginUserInfo;
      const { content, fileList, onSucceed, onFail } = draftInfo;
      const newCommentReply = {
        // 接口必传字段：
        CommentID: this.comment.ID,
        Content: content,
        Dimension: '', //
        UserAvatar: loginUser.avatar,
        Attachments: fileList.map(n => n.result),
        Url: this.notificationLink(),
        UrlParams: JSON.stringify({
          // fpath: encodeURIComponent(this.pageUrl),
          showComment: true,
          commentId: this.comment.ID,
        }),
      };

      try {
        const res = await saveReply(newCommentReply);
        console.log('SaveReply', res);
        if (!res || res.state !== '1' || !res.data) {
          onFail();
          return;
        }

        // mock new record, and override with real data
        Object.assign(
          newCommentReply,
          {
            ID: 'comment-reply-m-' + parseInt(Math.random() * 1000),
            ReplyTime: Date().toLocaleString(),
            UserID: loginUser.userId,
            UserName: loginUser.userName,
            Liked: false,
            LikeCount: 0,
            IsFavorite: false,
            FavoriteCount: 0,
            IsDeleted: false,
            CanCancel: true,
          },
          res.data,
        );

        // 调接口成功后清空输入框内容
        onSucceed();
        this.inputVisible = false;
        // 评论完将新添加评论展示出来
        this.comment.RepliesTop2.unshift(newCommentReply);
        this.comment.ReplyCount += 1;

        this.$emit('increase');
      } catch (error) {
        console.log(error);
        // this.$TM.Toast('发送失败');
        onFail();
      }
    },
    onReplyToReply(data) {
      this.comment.RepliesTop2.unshift(data);
      this.comment.ReplyCount += 1;
      this.$emit('increase');
    },
    onReplyDelete(data) {
      this.comment.ReplyCount -= 1;
      const currentReplies = this.comment.RepliesTop2.map(n => {
        if (n.ID === data.ID) {
          n.IsDeleted = true;
        }
        return n;
      });
      this.comment.RepliesTop2 = [];
      this.$emit('decrease');
      setTimeout(() => {
        this.comment.RepliesTop2 = currentReplies;
      });
    },
    showAllReplies() {
      if (this.disabled) return;
      this.commentRepliesPopupVisible = true;
    },
    onAddReplyInPopup() {
      this.comment.ReplyCount += 1;
      this.$emit('increase');
    },
    onDeleteReplyInPopup(data) {
      this.onReplyDelete(data);
    },
    onClickContent(e) {
      const el = e.target;
      // 如果点击了图片，则放大查看
      if (el.nodeName === 'IMG' && el.currentSrc) {
        // this.$TM.ImagePreview({images:[el.currentSrc]});
        const previwer = this.$refs.imagePreviewRef;
        if (previwer) {
          previwer.open(el.currentSrc);
        }
      } else if (el.dataset.userId) {
        // 点击了提及人，则弹出人员信息
        this.mentionedUserId = el.dataset.userId;
        this.personnelInfoVisible = true;
      } else {
        // 点击了内容，则直接弹出回复框
        this.onClickReply();
      }
    },
    handleDownloadFile(attachment) {
      const { AttachmentUrl, FileName } = attachment;
      saveAs({
        url: AttachmentUrl,
        fileName: FileName,
      });
    },
    onClickAttachment(attachment) {
      const ext = attachment.FileName.split('.').pop().toLowerCase();
      const previwer = this.$refs.imagePreviewRef;
      if (['png', 'jpg', 'jpeg', 'gif'].includes(ext) && previwer) {
        previwer.open(attachment.AttachmentUrl);
        return;
      }
      this.handleDownloadFile(attachment);
    },
  },
};
</script>

<style lang="scss" scoped></style>
